Introduction
In modern browsers, adding a video to your page is as easy as adding an image. No longer do you need to deal with special plug-ins or require crazy markup, you can do it with a single element.
The Markup
Let's jump in with a really simple example:
<video src="video.webm" controls>
</video>
That's all you need to embed a simple video on your page and show the basic controls so that a user can play, pause or otherwise control the video.
Specifying Sources
You can specify multiple source files by using the <source>
element. The source element lets you specify multiple formats as a
fallback in case the user's browser doesn't support one of them.
For example:
<video controls>
<source src="devstories.webm"
type='video/webm;codecs="vp8, vorbis"'/>
<source src="devstories.mp4"
type='video/mp4;codecs="avc1.42E01E, mp4a.40.2"'/>
</video>
When the browser parses the <source>
tag, it uses the
optional type attribute to help decide which file to download and play.
If the browser supports WebM and has the VP8 and Vorbis codecs, it will
play devstories.webm
, if not, it will check if it can play
MPEG-4 videos with the avc1.42E01E and mp4a.40.2 codecs, and so forth.
To improve performance, you should always include thetype
attribute in thesource
element. Otherwise the browser will need to load each video file until it can find one that it can play!
It's also a good idea to make sure that your videos are being served with the right MIME type. In some cases, the browser won't play the video if the MIME type isn't set properly.
Media Fragments
Adding a media
fragment to the media URL, you can specify the
exact portion you want to
play. To add a media fragment, you simply add
#t=[start_time][,end_time]
to the media URL. For example,
to play the video between seconds 10 through 20, you could specify:
<source src="devstories.webm#t=10,20"
type='video/webm;codecs="vp8, vorbis"' />
You can also specify the times in hours:minutes:seconds
,
such as #t=00:01:05
to start the video at one minute, five
seconds in. Or, to only play the first minute of the video, you would
specify #t=,00:01:00
. You need to make sure Range Requests
are supported by your server: check for Accept Ranges: bytes
.
It's on by default for Apache and many other servers, but worth checking.
Providing captions and subtitles
The <track>
element provides a simple, standardized
way to add subtitles, captions, screen reader descriptions and chapters
to your video, which improves accessibility but also makes it possible
for search engines to understand what's in the video. As well as
subtitles and captions, it's possible to put metadata in cues, for
example in JSON format. This can enable innovative use cases such as
DOM manipulation synchronised with video
playback.
<video controls style="width:640px;height:360px;" poster="poster.png">
<source src="devstories.webm"
type='video/webm;codecs="vp8, vorbis"' />
<source src="devstories.mp4"
type='video/mp4;codecs="avc1.42E01E, mp4a.40.2"' />
<track src="devstories-en.vtt" label="English subtitles"
kind="subtitles" srclang="en" default></track>
</video>
The <track>
element functions like a
<source>
element within the <video>
element, and has a src
attribute that points to a file in
WebVTT format. You can specify the label
that will be
displayed in the UI to the user, as well as the source language
(srclang
) and if there are multiple track elements, which
one should be used as the default.
Here's the first few lines of devstories-en.vtt:
WEBVTT FILE
1
00:00:00.500 --> 00:00:02.000 D:vertical A:start
The Web is always changing
2
00:00:02.500 --> 00:00:04.300
and the way we access it is changing
3
00:00:05.000 --> 00:00:07.000
The source of that change is <c.highlight>you</c>
Check out Getting Started With The Track Element for more information.
Attributes
The <video>
element has several special attributes
that can change or enhance its default behavior.
autoplay * |
Tells the browser to immediately start downloading the video and play it as soon as it can. Note that mobile browsers generally do not support this attribute, the user must tap the screen to begin video playback. |
preload |
Hint to the browser about whether optimistic downloading of the video itself or its metadata is considered worthwhile. Options are:
|
poster |
Provides an image to show before the video loads |
controls * |
Shows the default video controls (play, pause, etc) |
height & width |
Sets the width and height of the video in CSS pixels |
loop * |
Tells the browser to automatically loop the video |
muted * |
Mutes the audio from the video |
*indicates a binary attribute, which enables that behavior when the attribute is present, or has it's value set to anything.
Styling
Because the <video>
element is just another HTML
element, you can style it like any other element. You can add borders,
set the opacity, apply a filter or even do a 3D transform on the video.
For example, by applying filter: grayscale(100%);
to the
video element, you can turn your video into a black and white video:
As of the January 2014, the filter effect is only supported in WebKit and Blink based browsers.
JavaScript
Media elements like <video>
and
<audio>
have additional JavaScript functionality
beyond normal HTMLElements
that allow you to interact or
control the media.
Properties
currentTime |
Gets or sets the current playback position in seconds |
volume |
Gets or sets the current volume level for the video |
muted |
Gets or sets the mute state |
playbackRate |
Gets or sets the playback rate, where 1 is normal speed forward |
currentSrc |
Returns the current video source file the browser is playing |
videoWidth & videoHeight |
Returns the actual dimensions of the video, not the video element size |
Methods
load() |
Loads the video and reset the play head to the beginning of the video |
play() |
Plays the video from it’s current location |
pause() |
Pauses the video at the current location |
canPlayType(format) |
Tests to see whether the browser can play a specific type of
video, for example The browser will return:
|
Events*
canplaythrough |
Fired when enough data is available that the browser believes it can play the video completely without interruption |
ended |
Fired when the video has finished playing |
error |
Fired if an error occurs |
playing |
Fired when the video starts playing, for the first time, after being paused or when restarting |
progress |
Fired periodically to indicate the progress of downloading the video |
waiting |
Fired when an action is delayed pending the completion of another action |
loadedmetadata |
Fired when the browser has finished loading the metadata for the video and all attributes have been populated |
These are only a subset of the media events that may be fired. Refer to the Media events page on the Mozilla Developer Network for a complete listing.
There are many things that you can do using these JavaScript functions, events and attributes; you can build your own set of rich video controls, control multiple videos at the same time, jump to specific times within the video and plenty more. You can also use one of the many custom player controls that are available today to provide a rich experience.
Interacting with other elements
Video elements can interact with other elements like canvas
to provide a completely new experience. Canvas
'
drawImage
lets you grab a single frame from the
video
element, and draw it within the canvas
.
function grabScreenshot() {
ctx.drawImage(video, 0, 0, videoWidth, videoHeight);
var img = new Image();
img.src = canvas.toDataURL("image/png");
img.width = 120;
ssContainer.appendChild(img);
}
You can then modify the captured pixels and change the video in real time. For example, you could provide your own chroma-key effect, make the video explode when you click on it, or change the background color of the page based on the primary colors in the video. The possibilities are almost limitless!
The same technique of importing images can be also applied to WebGL. With WebGL you can import the frames of a video and render them on a spinning 3D cube.
Formats & codecs
You can think of a video file as a container (like a ZIP file), that contains the encoded video stream and an audio stream. There are many different types of container formats and unfortunately there isn't a single 'one-ring' format that will work in all browsers. If you're wondering why you need to use two encodings, be sure to read Licensing issues with H.264 video.
Thankfully, we can get coverage for all modern (and mobile) browsers using only two formats:
-
WebM
- uses the VP8 codec for video and the Vorbis codec for audio -
MP4
- uses the H.264 codec for video and the AAC codec for audio
WebM was designed specifically for serving video on the web, and has many benefits. Its low computational footprint means that it plays well on high-end desktops but also on low-powered devices like tablets or phones. High compression rates for video, which means videos can be downloaded faster, or you can improve the quality without a significant size increase. The encoding process is also significantly simpler with fewer profiles and sub-options.
Support for WebM is available natively in Chrome, Firefox and Opera, and can be added to Internet Explorer or desktop Safari by installing a plug-in. When not available natively or if the plug-in isn't installed, you'll need to provide the video encoded using the MP4 format.
The video chapter on www.diveintohtml5.info has an excellent section on how best to encode your videos. They recommend using ffmpeg for WebM videos and HandBrake for MP4 videos.
Mobile
Mobile provides some unique challenges for video. Sending a 1080p video to a mobile device like a phone doesn't make much sense, the video will likely be too big for the screen, and the bandwidth required to send the video may use all of the users limited data connection extremely quickly.
Browser vendors have accounted for this and have disabled the autoplay and preload attributes on mobile devices. It's also a good idea to include poster image that can be displayed until playback begins, though this does potentially require an additional download. This gives viewers a meaningful idea of content without needing to download video or start playback.
Further Reading
Encrypted Media Extensions - EME
Encrypted Media Extensions (sometimes referred to as EME) is a JavaScript API that enables web applications to interact with content protection systems, in order to allow playback of encrypted audio and video. EME is an extension to the HTMLMediaElement specification, and browser support is optional. If a browser does not support EME, it will simply silently fail to play the encrypted media.
Streaming video with the MediaSource API
The
MediaSource API extends the HTMLMediaElement
to allow
JavaScript to generate media streams for playback. Allowing JavaScript to
generate streams facilitates a variety of use cases like adaptive
streaming and time shifting live streams.
Summary
Including video on the modern web is easier than ever before and opens some amazing new possibilities. What will you do next?